package com.example.concurrent.chapter18;

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * @author Create By Liuqz
 * @date 2018/11/27 11:24
 */
public class IntegerAccumulator {

    private int init;

    //构造时传入初始值
    public IntegerAccumulator(int init) {
        this.init = init;
    }

    //对初始值增加i
    public int add(int i) {
        this.init += i;
        return this.init;
    }

    //返回当前的初始值
    public int getValue() {
        return this.init;
    }

    /**
     * 这段程序没有对共享资源进行共享锁的保护,也没有进行不可变的设计,这程序运行中偶尔会出现错误的情况
     * ERROR : 13213 + 112 = 13437
     * ERROR : 15778 + 122 = 16022
     * ERROR : 18417 + 130 = 18677
     * @param args
     */
    public static void main(String[] args) {
        //定义累加器,并且将设置初始值为0
        IntegerAccumulator accumulator = new IntegerAccumulator(0);
        IntStream.range(0,3).forEach(i -> new Thread(() -> {
            int inc = 0;
            while (true) {
                //没有进行共享锁保护的代码
                //首先获取old value
//                int oldValue = accumulator.getValue();

                //调用add方法计算
//                int result = accumulator.add(inc);

                //进行同步锁保护
                int oldValue;
                int result;

                //使用class实例作为同步锁
                synchronized (IntegerAccumulator.class) {
                    oldValue = accumulator.getValue();
                    result = accumulator.add(inc);
                }

                System.out.println(oldValue + " + " + inc + " = " +result);
                //验证不合理信息,则输出错误信息
                if (inc + oldValue != result) {
                    System.err.println("ERROR : " + oldValue + " + " + inc + " = " + result);
                }
                inc++;
                //模拟延迟
                showly();
            }
        }).start());
    }

    private static void showly() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
